// 加密工具类
// @/utils/crypto.ts

export class CryptoUtil {
  private readonly algorithm = 'AES'
  private readonly keySize = 256
  private readonly ivSize = 16
  private secretKey: string

  constructor(secretKey?: string) {
    // 使用环境变量或默认密钥
    this.secretKey = secretKey || import.meta.env.VITE_CRYPTO_KEY || this.generateDefaultKey()
  }

  // 生成默认密钥
  private generateDefaultKey(): string {
    // 基于设备信息生成唯一密钥
    const deviceInfo = uni.getSystemInfoSync()
    const seed = `${deviceInfo.brand}-${deviceInfo.model}-${deviceInfo.platform}`
    return this.hash(seed).substring(0, 32)
  }

  // 加密
  async encrypt(data: string): Promise<string> {
    try {
      // 生成随机 IV
      const iv = this.generateRandomString(this.ivSize)
      
      // 简单的 XOR 加密（由于 UniApp 环境限制）
      const encrypted = this.xorEncrypt(data, this.secretKey + iv)
      
      // 返回 IV + 加密数据
      return this.base64Encode(iv + ':' + encrypted)
    } catch (error) {
      console.error('加密失败:', error)
      throw new Error('数据加密失败')
    }
  }

  // 解密
  async decrypt(encryptedData: string): Promise<string> {
    try {
      const decoded = this.base64Decode(encryptedData)
      const [iv, encrypted] = decoded.split(':')
      
      if (!iv || !encrypted) {
        throw new Error('加密数据格式错误')
      }
      
      // XOR 解密
      return this.xorEncrypt(encrypted, this.secretKey + iv)
    } catch (error) {
      console.error('解密失败:', error)
      throw new Error('数据解密失败')
    }
  }

  // 同步加密（性能较低，建议使用异步版本）
  encryptSync(data: string): string {
    const iv = this.generateRandomString(this.ivSize)
    const encrypted = this.xorEncrypt(data, this.secretKey + iv)
    return this.base64Encode(iv + ':' + encrypted)
  }

  // 同步解密
  decryptSync(encryptedData: string): string {
    const decoded = this.base64Decode(encryptedData)
    const [iv, encrypted] = decoded.split(':')
    
    if (!iv || !encrypted) {
      throw new Error('加密数据格式错误')
    }
    
    return this.xorEncrypt(encrypted, this.secretKey + iv)
  }

  // XOR 加密/解密
  private xorEncrypt(data: string, key: string): string {
    let result = ''
    for (let i = 0; i < data.length; i++) {
      result += String.fromCharCode(
        data.charCodeAt(i) ^ key.charCodeAt(i % key.length)
      )
    }
    return result
  }

  // 哈希函数
  hash(data: string, algorithm: 'md5' | 'sha1' | 'sha256' = 'sha256'): string {
    // 简单的哈希实现（实际项目中应使用专业的加密库）
    let hash = 0
    
    if (algorithm === 'md5') {
      // 简化的 MD5 实现
      for (let i = 0; i < data.length; i++) {
        const char = data.charCodeAt(i)
        hash = ((hash << 5) - hash) + char
        hash = hash & hash
      }
    } else {
      // 简化的 SHA 实现
      for (let i = 0; i < data.length; i++) {
        const char = data.charCodeAt(i)
        hash = ((hash << 5) - hash) + char
        hash = hash & hash
      }
      hash = Math.abs(hash)
    }
    
    return hash.toString(16).padStart(algorithm === 'sha256' ? 64 : 32, '0')
  }

  // Base64 编码
  base64Encode(data: string): string {
    try {
      // 使用 uni-app 提供的方法
      return btoa(unescape(encodeURIComponent(data)))
    } catch {
      // 备用方案
      return this.customBase64Encode(data)
    }
  }

  // Base64 解码
  base64Decode(data: string): string {
    try {
      return decodeURIComponent(escape(atob(data)))
    } catch {
      return this.customBase64Decode(data)
    }
  }

  // 自定义 Base64 编码
  private customBase64Encode(data: string): string {
    const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    let result = ''
    let i = 0
    
    while (i < data.length) {
      const a = data.charCodeAt(i++)
      const b = i < data.length ? data.charCodeAt(i++) : 0
      const c = i < data.length ? data.charCodeAt(i++) : 0
      
      const bitmap = (a << 16) | (b << 8) | c
      
      result += base64Chars.charAt((bitmap >> 18) & 63)
      result += base64Chars.charAt((bitmap >> 12) & 63)
      result += i - 2 < data.length ? base64Chars.charAt((bitmap >> 6) & 63) : '='
      result += i - 1 < data.length ? base64Chars.charAt(bitmap & 63) : '='
    }
    
    return result
  }

  // 自定义 Base64 解码
  private customBase64Decode(data: string): string {
    const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    let result = ''
    let i = 0
    
    data = data.replace(/[^A-Za-z0-9+/]/g, '')
    
    while (i < data.length) {
      const encoded1 = base64Chars.indexOf(data.charAt(i++))
      const encoded2 = base64Chars.indexOf(data.charAt(i++))
      const encoded3 = base64Chars.indexOf(data.charAt(i++))
      const encoded4 = base64Chars.indexOf(data.charAt(i++))
      
      const bitmap = (encoded1 << 18) | (encoded2 << 12) | (encoded3 << 6) | encoded4
      
      result += String.fromCharCode((bitmap >> 16) & 255)
      if (encoded3 !== 64) result += String.fromCharCode((bitmap >> 8) & 255)
      if (encoded4 !== 64) result += String.fromCharCode(bitmap & 255)
    }
    
    return result
  }

  // 生成随机字符串
  generateRandomString(length: number): string {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    let result = ''
    
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    
    return result
  }

  // 生成 UUID
  generateUUID(): string {
    const template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
    
    return template.replace(/[xy]/g, (c) => {
      const r = Math.random() * 16 | 0
      const v = c === 'x' ? r : (r & 0x3 | 0x8)
      return v.toString(16)
    })
  }

  // 检查是否为加密数据
  isEncrypted(data: string): boolean {
    try {
      // 检查是否为 Base64 格式
      const decoded = this.base64Decode(data)
      return decoded.includes(':') && decoded.split(':').length === 2
    } catch {
      return false
    }
  }

  // 密码加密（单向）
  hashPassword(password: string, salt?: string): string {
    const actualSalt = salt || this.generateRandomString(16)
    const hashed = this.hash(password + actualSalt)
    return `${actualSalt}:${hashed}`
  }

  // 验证密码
  verifyPassword(password: string, hashedPassword: string): boolean {
    const [salt, hash] = hashedPassword.split(':')
    if (!salt || !hash) return false
    
    const computedHash = this.hash(password + salt)
    return computedHash === hash
  }

  // 对象加密
  async encryptObject<T>(obj: T): Promise<string> {
    const jsonStr = JSON.stringify(obj)
    return this.encrypt(jsonStr)
  }

  // 对象解密
  async decryptObject<T>(encryptedData: string): Promise<T> {
    const jsonStr = await this.decrypt(encryptedData)
    return JSON.parse(jsonStr)
  }

  // 生成密钥对（简化版）
  generateKeyPair(): {
    publicKey: string
    privateKey: string
  } {
    const privateKey = this.generateRandomString(32)
    const publicKey = this.hash(privateKey).substring(0, 32)
    
    return {
      publicKey,
      privateKey
    }
  }

  // 使用公钥加密
  encryptWithPublicKey(data: string, publicKey: string): string {
    return this.xorEncrypt(data, publicKey)
  }

  // 使用私钥解密
  decryptWithPrivateKey(encryptedData: string, privateKey: string): string {
    const publicKey = this.hash(privateKey).substring(0, 32)
    return this.xorEncrypt(encryptedData, publicKey)
  }

  // 数字签名（简化版）
  sign(data: string, privateKey: string): string {
    const hash = this.hash(data)
    return this.hash(hash + privateKey)
  }

  // 验证签名
  verify(data: string, signature: string, publicKey: string): boolean {
    const hash = this.hash(data)
    const expectedSignature = this.hash(hash + publicKey)
    return signature === expectedSignature
  }

  // 静态方法（兼容旧版本）
  static encrypt(data: string): string {
    const instance = new CryptoUtil()
    return instance.encryptSync(data)
  }

  static decrypt(encryptedData: string): string {
    const instance = new CryptoUtil()
    return instance.decryptSync(encryptedData)
  }

  static generateUUID(): string {
    const instance = new CryptoUtil()
    return instance.generateUUID()
  }

  static hash(data: string): string {
    const instance = new CryptoUtil()
    return instance.hash(data)
  }

  // 验证密码强度
  static validatePasswordStrength(password: string): {
    score: number
    level: 'weak' | 'medium' | 'strong' | 'very-strong'
    suggestions: string[]
  } {
    let score = 0
    const suggestions: string[] = []

    // 长度检查
    if (password.length >= 8) score += 1
    else suggestions.push('密码长度至少8位')

    if (password.length >= 12) score += 1

    // 复杂度检查
    if (/[a-z]/.test(password)) score += 1
    else suggestions.push('包含小写字母')

    if (/[A-Z]/.test(password)) score += 1
    else suggestions.push('包含大写字母')

    if (/\d/.test(password)) score += 1
    else suggestions.push('包含数字')

    if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) score += 1
    else suggestions.push('包含特殊字符')

    // 判断强度等级
    let level: 'weak' | 'medium' | 'strong' | 'very-strong'
    if (score <= 2) level = 'weak'
    else if (score <= 3) level = 'medium'
    else if (score <= 5) level = 'strong'
    else level = 'very-strong'

    return { score, level, suggestions }
  }

  // 敏感信息脱敏
  static maskSensitiveData(data: string, type: 'phone' | 'email' | 'idCard' | 'bankCard' = 'phone'): string {
    if (!data) return data

    switch (type) {
      case 'phone':
        // 手机号脱敏：138****1234
        return data.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
      
      case 'email':
        // 邮箱脱敏：u***@example.com
        return data.replace(/(.{1,3}).*@/, '$1***@')
      
      case 'idCard':
        // 身份证脱敏：前3位和后4位显示
        if (data.length >= 8) {
          const start = data.substring(0, 3)
          const end = data.substring(data.length - 4)
          const middle = '*'.repeat(data.length - 7)
          return start + middle + end
        }
        return data
      
      case 'bankCard':
        // 银行卡脱敏：显示后4位
        if (data.length >= 8) {
          const end = data.substring(data.length - 4)
          const middle = '*'.repeat(data.length - 4)
          return middle + end
        }
        return data
      
      default:
        return data
    }
  }
}

// 创建默认实例
export const crypto = new CryptoUtil()

// 使用示例：
// import { CryptoUtil } from '@/utils/crypto'
//
// const crypto = new CryptoUtil()
//
// // 加密字符串
// const encrypted = await crypto.encrypt('sensitive data')
// const decrypted = await crypto.decrypt(encrypted)
//
// // 哈希
// const hash = crypto.hash('password')
//
// // 密码处理
// const hashedPassword = crypto.hashPassword('user_password')
// const isValid = crypto.verifyPassword('user_password', hashedPassword)
//
// // 对象加密
// const encryptedObj = await crypto.encryptObject({ secret: 'data' })
// const decryptedObj = await crypto.decryptObject(encryptedObj)

// 默认导出（兼容旧版本）
export default CryptoUtil 